<?php

/**
 * Функция компилятора Smarty для вставки блока на страницу.
 *
 * Параметры блока:
 * - module (*) — наименование модуля, которому принадлежит блок;
 * - name   (*) — наименование блока;
 * - output     — флаг, указывающий, что данные нужно вывести непосредственно в шаблон;
 * - file       — путь к файлу шаблона, по которому нужно отобразить данные шаблона;
 * - assign     — наименование переменной, которой нужно присвоить данные шаблона.
 *
 *   (*) — обязательные параметры
 *
 * В случае, если ни output, ни file, ни assign не указаны, путь к файлу шаблона
 * вида {module}/block/{name}.tpl формируется автоматически.
 *
 * @param   string          $tag_attrs
 * @param   Smarty_Compiler $compiler
 * @return  string
 */
function smarty_compiler_block($tag_attrs, &$compiler) 
{
    $params = $compiler->_parse_attrs($tag_attrs);

    if (!isset($params['module'])) {
        $compiler->_syntax_error('block: missing "module" parameter', E_USER_WARNING);
        return false;
    }

    $module = $params['module'];

    if (!isset($params['name'])) {
        $compiler->_syntax_error('block: missing "name" parameter', E_USER_WARNING);
        return false;
    }

    $name = $params['name'];

    if (isset($params['file'])) {
        $file = $params['file'];
    }

    if (isset($params['assign'])) {
        $assign = $params['assign'];
    }

    if (isset($params['output'])) {
        $output = true;
    }

    // если не указано ни файла шаблона, ни переменной для присваивания,
    // формируем путь к шаблону руками, т.к. в большинстве случаев этот путь
    // формируется по одному и тому же правилу.
    if (!isset($output) && !isset($file) && !isset($assign)) {

        // вот, собственно, правило :)
        $file = $module . ' . "/block/" . ' . $name . ' . ".tpl"';
    }

    unset($params['module'], $params['name'], $params['file'], $params['assign'], $params['output']);

    $code = '$vars = Kernel_Module::factory(' . $module . ')->block(' . $name . ', ' . smarty_compiler_block_export($params) . ');';

    switch (true) {

        // подключаем файл шаблона и передаем в его контекст данные блока
        case isset($output):
            $code .= 'echo $vars;';
            break;

        // подключаем файл шаблона и передаем в его контекст данные блока
        case isset($file):
            $code .= '$_smarty_tpl_vars = $this->_tpl_vars;'
                . '$this->_smarty_include(array("smarty_include_tpl_file" => ' . $file . ', "smarty_include_vars" => (array)$vars));'
                . '$this->_tpl_vars = $_smarty_tpl_vars;'
                . 'unset($_smarty_tpl_vars);';
            break;

        // передаем данные блока в переменную
        case isset($assign):
            $code .= '$this->assign(' . $assign . ', $vars);';
            break;
    }

    return $code;
}

/**
 * Формирует параметры подключаемого блока. Фактически, дублирует код из
 * Smarty_Compiler::_compile_include_tag() и очень похож на var_export().
 *
 * @param   array   $params
 * @return  string
 */
function smarty_compiler_block_export($params) 
{
    $stack = array();
    foreach ($params as $name => $value) {
        $stack[] = '"' . $name . '" => ' . $value;
    }
    return 'array(' . implode(', ', $stack) . ')';
}
